#ifndef __LOG_BUFFER_QUEUE__
#define __LOG_BUFFER_QUEUE__

#include<iostream>
#include<mutex>
#include<condition_variable>
#include<chrono>

#include<cassert>

#include"level.hpp"

template<class T>
class Log_buffer_queue
{
public:
    Log_buffer_queue():_buffer_arr(new T[_capacity]){}

    explicit Log_buffer_queue(int max_size,bool debug=false)
    {
        if(max_size<=0)
        {
            ERR_LOG("max_size is illegal!\n");
            exit(-1);
            // throw
        }
        _buffer_debug=debug;
        _capacity=max_size;
        _buffer_arr=new T[_capacity];
    }

    //清空阻塞队列，重置状态
    void clear()
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_debug)
        {
            _buffer_rcnt=0;
            _buffer_wcnt=0;
        }
        _buffer_first=-1;
        _buffer_end=-1;
        _buffer_size=0;
    }

    //用于调试接口
    //获得读事件数量
    //为什么这几个都需要const？
    int get_rcnt() const
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_debug)return _buffer_rcnt;
        WAR_LOG("this method is invalid when debug is false!\n");
        return -1;
    }

    //获得写事件数量
    int get_wcnt() const
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_debug)return _buffer_wcnt;
        WAR_LOG("this method is invalid when debug is false!\n");
        return -1;
    }

    //获取当前队列大小
    int get_size() const
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        assert(_buffer_size>=0&&_buffer_size<=_capacity);
        return _buffer_size;
    }

    //判断队列是否满
    bool is_full() const
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        return _buffer_size==_capacity?true:false;
    }

    //判断队列是否空
    bool is_empty() const
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        return _buffer_size==0?true:false;
    }

    //获取队列容量
    int get_capacity() const
    {
        return _capacity;
    }

    //获得队列最前的日志
    bool front(T &value)
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_size==0)return false;
        value=_buffer_arr[_buffer_first+1];
        return true;
    }

    //获得队列最后的日志
    bool back(T& value)
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_size==0)return false;
        value=_buffer_arr[_buffer_end];
        return true;
    }

    //唤醒所有线程
    void notify()
    {
        _buffer_cond.notify_all();
    }

    //加入日志到队列，若队列已满，唤醒其他线程并返回，否则，加入日志并唤醒其他线程
    bool push(const T& item)
    {
        std::unique_lock<std::mutex> mtx(_buffer_mutex);
        if(_buffer_size>=_capacity)
        {
            _buffer_cond.notify_all();
            return false;
        }

        _buffer_end=(_buffer_end+1)%_capacity;
        _buffer_arr[_buffer_end]=item;
        _buffer_size++;

        if(_buffer_debug)_buffer_wcnt++;
        _buffer_cond.notify_all();

        return true;
    }

    //弹出日志到队列，若队列为空，线程等待，否则，弹出日志
    //重载加入ms_timeout,指定时间段，当线程没有收到通知或者时间段内，处于阻塞
    bool pop(T& item)
    {
        std::unique_lock<std::mutex> mtx(_buffer_mutex);
        if(_buffer_size<=0)
        {
            _buffer_cond.wait(mtx);
            if(_buffer_size<=0)return false;
        }

        _buffer_first=(_buffer_first+1)%_capacity;
        item=_buffer_arr[_buffer_first];
        _buffer_size--;

        if(_buffer_debug)_buffer_rcnt++;
        return true;
    }

    //wait_for作用？？cv_status作用？？
    bool pop(T& item,int ms_timeout)
    {
        std::unique_lock<std::mutex> mtx(_buffer_mutex);
        if(_buffer_size<=0)
        {
            if(_buffer_cond.wait_for(mtx,std::chrono::microseconds(ms_timeout))==std::cv_status::timeout)
            return false;
        }
        if(_buffer_size<=0)return false;

        _buffer_first=(_buffer_first+1)%_capacity;
        item=_buffer_arr[_buffer_first];
        _buffer_size--;

        if(_buffer_debug)_buffer_rcnt++;
        return true;
    }

    ~Log_buffer_queue()
    {
        std::lock_guard<std::mutex> mtx(_buffer_mutex);
        if(_buffer_arr!=nullptr)delete [] _buffer_arr;
    }

private:
    T* _buffer_arr;                     //阻塞队列
    int _capacity=1000;                 //队列容量

    bool _buffer_debug=false;           //是否启动调试功能
    long long _buffer_rcnt=0;           //调试功能，读日志数
    long long _buffer_wcnt=0;           //调试功能，写日志数

    int _buffer_first=-1;               //队列开始
    int _buffer_end=-1;                 //队列末尾
    int _buffer_size=0;                 //队列长度

    mutable std::mutex _buffer_mutex;       
    std::condition_variable _buffer_cond;   
};

#endif